/*
 *  Copyright (C) 2010 Interactive Media Management
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package dk.i2m.converge.plugins.videooutput;

import com.xuggle.mediatool.MediaToolAdapter;
import com.xuggle.mediatool.event.IVideoPictureEvent;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import org.apache.commons.lang.WordUtils;

public class NewsItemOverlay extends MediaToolAdapter {

    private static final Logger LOGGER = Logger.getLogger(NewsItemOverlay.class.getName());
    private static final Font HEADLINE_FONT = new Font("SanSerif", Font.BOLD, 33);
    private static final Font HEADLINES_FONT = new Font("SanSerif", Font.BOLD, 28);
    private static final Font CONTENT_FONT = new Font("SanSerif", Font.BOLD, 19);
    private static final Color TEXT_BACKGROUND = new Color(0, 0, 0, 100);
    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
    private static final int DEFAULT_TIME_PER_STORY = 10000000;
    private static final String DEFAULT_TITLE = "LATEST HEADLINES";
    private List<VideoNewsItem> newsItems = new ArrayList<VideoNewsItem>();
    private int timePerStory;
    private String title;

    public NewsItemOverlay(List<VideoNewsItem> newsItems, int timePerStory, String title) {
        this.newsItems = newsItems;
        this.timePerStory = timePerStory;
        this.title = title;
    }

    public NewsItemOverlay(List<VideoNewsItem> newsItems, int timePerStory) {
        this(newsItems, timePerStory, DEFAULT_TITLE);
    }

    public NewsItemOverlay(List<VideoNewsItem> newsItems, String title) {
        this(newsItems, DEFAULT_TIME_PER_STORY, title);
    }

    public NewsItemOverlay(List<VideoNewsItem> newsItems) {
        this(newsItems, DEFAULT_TIME_PER_STORY, DEFAULT_TITLE);
    }

    /** {@inheritDoc} */
    @Override
    public void onVideoPicture(IVideoPictureEvent event) {

        // get the current image
        BufferedImage image = event.getImage();
        Graphics2D g = image.createGraphics();

        // turn on anti-alias for texts
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        // determine what to do at the current time
        if (event.getPicture().getTimeStamp() < timePerStory) {
            generateOverview(image, g);
        } else {
            int storyIndex = (int) Math.ceil(event.getPicture().getTimeStamp() / timePerStory);

            try {
                generateStory(image, g, newsItems.get(storyIndex - 1));
            } catch (IndexOutOfBoundsException ex) {
                LOGGER.log(Level.INFO, ex.getMessage());
            }
        }

        super.onVideoPicture(event);
    }

    private void generateOverview(BufferedImage image, Graphics2D g) {
        g.setFont(HEADLINE_FONT);

        Rectangle2D bounds = g.getFont().getStringBounds(title, g.getFontRenderContext());
        int textWidth = (int) (bounds.getWidth());
        int x = (image.getWidth() - textWidth) / 2;
        g.setColor(TEXT_BACKGROUND);
        g.fillRect(x - 20, 75, (int) bounds.getWidth() + 40, (int) bounds.getHeight() + 5);

        g.setColor(Color.BLACK);
        g.drawString(title, x, 110);

        g.setColor(Color.WHITE);
        g.drawString(title, x - 1, 109);

        int left = 100;
        int top = 200;

        for (VideoNewsItem ni : newsItems) {
            g.setFont(HEADLINES_FONT);
            g.setColor(Color.BLACK);
            g.drawString(ni.getHeadline(), left, top);
            g.setColor(Color.WHITE);
            g.drawString(ni.getHeadline(), left - 1, top - 1);
            top += 50;
        }
    }

    private void generateStory(BufferedImage image, Graphics2D g, VideoNewsItem item) {
        try {
            g.setFont(HEADLINE_FONT);
            Rectangle2D bounds = g.getFont().getStringBounds(item.getHeadline().toUpperCase(), g.getFontRenderContext());
            int textWidth = (int) (bounds.getWidth());
            int x = (image.getWidth() - textWidth) / 2;
            g.setColor(Color.white);
            g.fillRect(x - 10, 75, (int) bounds.getWidth() + 20, (int) bounds.getHeight() + 5);
            g.setColor(Color.BLACK);
            g.drawString(item.getHeadline().toUpperCase(), x, 110);
            g.setFont(CONTENT_FONT);

            String wrapped = WordUtils.wrap(item.getContent(), 52, LINE_SEPARATOR, true);
            String[] lines = wrapped.split(LINE_SEPARATOR);

            int lineSpacing = 29;

            int contentX = 400;
            int contentY = 180;
            g.setColor(TEXT_BACKGROUND);
            g.fillRect(contentX - 5, contentY - 20, 550, (lineSpacing * lines.length) + 5);
            g.setColor(Color.white);


            for (String line : lines) {
                g.drawString(line, contentX, contentY);
                contentY += lineSpacing;
            }
            BufferedImage bImg = ImageIO.read(new URL(item.getImageUrl()));
            int w = bImg.getWidth();
            int h = bImg.getHeight();
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(bImg, 20, 180 - 20, w - 90, h, 0, 0, w, h, null);
        } catch (IOException ex) {
            LOGGER.log(Level.WARNING, ex.getMessage());
            LOGGER.log(Level.FINE, "", ex);
        }

    }
}
